package com.mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.collision.PhysicsCollisionEvent;
import com.jme3.bullet.collision.PhysicsCollisionListener;


import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;

import com.jme3.input.InputManager;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseButtonTrigger;

public class Main extends SimpleApplication implements PhysicsCollisionListener, ActionListener {

    public static void main(String[] args) {
        Main app = new Main();
        app.start();
    }
    
    private RigidBodyControl playerBody;
    private boolean isOnGround = false;
    
    @Override
    public void simpleInitApp() {
        Box b = new Box(1, 1, 1);
        Geometry geom = new Geometry("Player", b);
        Material mat = new Material(assetManager, 
                                    "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setColor("Color", ColorRGBA.Blue);
        geom.setMaterial(mat);
        
        CollisionShape boxShape = new BoxCollisionShape(new Vector3f(1,1,1));
        playerBody = new RigidBodyControl(boxShape, 1f);
        geom.addControl(playerBody);
        BulletAppState bulletAppState = new BulletAppState();
        stateManager.attach(bulletAppState);
        PhysicsSpace physicsSpace = bulletAppState.getPhysicsSpace();
        physicsSpace.add(playerBody);

        rootNode.attachChild(geom);
        
        Box platform = new Box(10, 1, 10);
        Geometry geomP = new Geometry("redPlatform", platform);
        geomP.setLocalTranslation(0, -5, 0);
        Material matP = new Material(assetManager, 
                                     "Common/MatDefs/Misc/Unshaded.j3md");
        matP.setColor("Color", ColorRGBA.Red);
        geomP.setMaterial(matP);
        
        CollisionShape pShape = new BoxCollisionShape(new Vector3f(10, 1, 10));
        RigidBodyControl pRigidBody = new RigidBodyControl(pShape, 0f);
        geomP.addControl(pRigidBody);
        physicsSpace.add(pRigidBody);
        physicsSpace.addCollisionListener(this);
        
        rootNode.attachChild(geomP);
        
        inputManager.addMapping("Jump", new KeyTrigger(KeyInput.KEY_SPACE));
        inputManager.addMapping("Pause", new KeyTrigger(KeyInput.KEY_P));
        inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_E));
        inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_R));
        inputManager.addMapping("Rotate", new KeyTrigger(KeyInput.KEY_SPACE), 
                                new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
        
        inputManager.addListener(analogListener, "Left", "Right", "Rotate");
        inputManager.addListener(this, "Jump", "Pause");
    }
    
    @Override
    public void simpleUpdate(float tpf) {
//        System.out.println(isOnGround);
    }

    @Override
    public void simpleRender(RenderManager rm) {
        //TODO: add render code
    }
    
    @Override
    public void collision(PhysicsCollisionEvent event) {
//        System.out.println(event);
//        
//        System.out.printf("   Collision %s ; %s\n", 
//                          event.getNodeA().getName(), event.getNodeB().getName());
        if (event.getNodeA().getName().equals("Player") &&
            event.getNodeB().getName().equals("redPlatform")) {
            isOnGround = true;
        }
    }


    @Override
    public void onAction(String name, boolean isPressed, float f) {
        if (name.equals("Jump") && isPressed && isOnGround) {
            playerBody.applyImpulse(new Vector3f(0, 10, 0), Vector3f.ZERO);
            isOnGround = false;
        }
        else if (name.equals("Left") && isPressed && isOnGround) {
            playerBody.applyImpulse(new Vector3f(1, 0, 0), Vector3f.ZERO);
        }
    }
    
    final private AnalogListener analogListener = new AnalogListener() 
    {
       @Override
        public void onAnalog(String name, float value, float tpf) 
        {
            switch (name) {
                case "Rotate":
                    playerBody.setAngularVelocity(new Vector3f(playerBody.getAngularVelocity().x + value, 0, 0));

                    break;
                case "Left":
                    playerBody.applyImpulse(new Vector3f(value, 0, 0), Vector3f.ZERO);
                    break;
                case "Right":
                    playerBody.applyImpulse(new Vector3f(-value, 0, 0), Vector3f.ZERO);
                    break;
            }
        }
    };
}

